package com.spsoft.dmzeinvoice.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.google.common.reflect.TypeToken;
import com.spsoft.core.constants.CommonConstants;
import com.spsoft.core.model.Result;
import com.spsoft.core.model.leqidmz.param.*;
import com.spsoft.core.model.leqidmz.response.*;
import com.spsoft.dmzeinvoice.common.enums.LeqiAbilityEnum;
import com.spsoft.dmzeinvoice.common.enums.LeqiApiEnum;
import com.spsoft.dmzeinvoice.common.enums.TdysEnum;
import com.spsoft.dmzeinvoice.common.utils.LeqiMockUtil;
import com.spsoft.dmzeinvoice.common.utils.LeqiResultUtil;
import com.spsoft.dmzeinvoice.common.utils.RestTemplateUtil;
import com.spsoft.dmzeinvoice.model.vo.LeqiResult;
import com.spsoft.dmzeinvoice.service.VmsRedInvoiceService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.lang.reflect.Type;

@Slf4j
@Service
@RequiredArgsConstructor
@SuppressWarnings({"unchecked"})
public class VmsRedInvoiceServiceImpl implements VmsRedInvoiceService {

    private final RestTemplateUtil restTemplateUtil;

    // 是否返回模拟数据
    @Value("${leqi.mockFlag}")
    private boolean mockFlag;

    // 调用乐企的请求地址
    @Value("${leqi.url}")
    private String url;

    // 乐企接入单位平台编号
    @Value("${leqi.jrdwptbh}")
    private String jrdwptbh;

    // 乐企沙箱测试标志
    @Value("${leqi.sxcsbz:}")
    private String sxcsbz;

    /**
     * 数电红字确认单申请
     */
    @Override
    public Result<ApplyRedConfirmVO> applyRedConfirm(ApplyRedConfirmDetailParam param) {
        // 组装请求头
        LeqiHeader leqiHeader = buildHeader(param, LeqiApiEnum.QDHZQRDSQ);

        String responseStr;
        String requestJson = JSONObject.toJSONString(param);

        if (mockFlag) {
            // Mock数据
            responseStr = LeqiMockUtil.getApplyRedConfirmStr();
        } else {
            // 调乐企接口
            responseStr = restTemplateUtil.postLeQi(leqiHeader, requestJson);
        }

        Type type = new TypeToken<LeqiResult<String>>(){}.getType();
        LeqiResult<String> leqiResult = LeqiResultUtil.jsonToLeqiResult(responseStr, type);
        LeqiResult.ErrorInfo errorInfo = leqiResult.getResponse().getError();
        // 有error节点，返回error
        if (errorInfo != null) {
            return Result.ERRORT(errorInfo.getCode(), errorInfo.getMessage());
        }
        ApplyRedConfirmVO resultVo = JSONObject.parseObject(leqiResult.getResponse().getData(), ApplyRedConfirmVO.class);
        // 业务层不为00，返回error
        if (!CommonConstants.LEQI_SUCCESS.equals(resultVo.getReturncode())) {
            return Result.ERRORT(resultVo.getReturncode(), resultVo.getReturnmsg());
        }

        return Result.OK(resultVo);
    }

    /**
     * 数电红字确认单确认
     */
    @Override
    public Result<ConfirmRedConfirmVO> confirmRedConfirm(ConfirmRedConfirmParam param) {
        // 组装请求头
        LeqiHeader leqiHeader = buildHeader(param, LeqiApiEnum.QDHZQRDQR);

        String responseStr;
        String requestJson = JSONObject.toJSONString(param);

        if (mockFlag) {
            // Mock数据
            responseStr = LeqiMockUtil.getConfirmRedConfirmStr();
        } else {
            // 调乐企接口
            responseStr = restTemplateUtil.postLeQi(leqiHeader, requestJson);
        }

        Type type = new TypeToken<LeqiResult<String>>(){}.getType();
        LeqiResult<String> leqiResult = LeqiResultUtil.jsonToLeqiResult(responseStr, type);
        LeqiResult.ErrorInfo errorInfo = leqiResult.getResponse().getError();
        // 有error节点，返回error
        if (errorInfo != null) {
            return Result.ERRORT(errorInfo.getCode(), errorInfo.getMessage());
        }
        ConfirmRedConfirmVO resultVo = JSONObject.parseObject(leqiResult.getResponse().getData(), ConfirmRedConfirmVO.class);
        // 业务层不为00，返回error
        if (!CommonConstants.LEQI_SUCCESS.equals(resultVo.getReturncode())) {
            return Result.ERRORT(resultVo.getReturncode(), resultVo.getReturnmsg());
        }

        return Result.OK(resultVo);
    }

    /**
     * 查询数电红字确认单明细信息
     */
    @Override
    public Result<QueryRedConfirmDetailVO> queryRedConfirmDetail(QueryRedConfirmDetailParam param) {
        // 组装请求头
        LeqiHeader leqiHeader = buildHeader(param, LeqiApiEnum.CXQDHZQRDMX);

        String responseStr;
        String requestJson = JSONObject.toJSONString(param);

        if (mockFlag) {
            // Mock数据
            responseStr = LeqiMockUtil.getRedConfirmDetailStr();
        } else {
            // 调乐企接口
            responseStr = restTemplateUtil.postLeQi(leqiHeader, requestJson);
        }

        Type type = new TypeToken<LeqiResult<String>>(){}.getType();
        LeqiResult<String> leqiResult = LeqiResultUtil.jsonToLeqiResult(responseStr, type);
        LeqiResult.ErrorInfo errorInfo = leqiResult.getResponse().getError();
        // 有error节点，返回error
        if (errorInfo != null) {
            return Result.ERRORT(errorInfo.getCode(), errorInfo.getMessage());
        }
        QueryRedConfirmDetailVO resultVo = JSONObject.parseObject(leqiResult.getResponse().getData(), QueryRedConfirmDetailVO.class);
        // 业务层不为00，返回error
        if (!CommonConstants.LEQI_SUCCESS.equals(resultVo.getReturncode())) {
            return Result.ERRORT(resultVo.getReturncode(), resultVo.getReturnmsg());
        }

        return Result.OK(resultVo);
    }

    /**
     * 查询数电红字确认单列表信息
     */
    @Override
    public Result<QueryRedConfirmListVO> queryRedConfirmList(QueryRedConfirmListParam param){
        // 组装请求头
        LeqiHeader leqiHeader = buildHeader(param, LeqiApiEnum.CXQDHZQRDLB);

        String responseStr;
        String requestJson = JSONObject.toJSONString(param);

        if (mockFlag) {
            // Mock数据
            responseStr = LeqiMockUtil.getRedConfirmListStr();
        } else {
            // 调乐企接口
            responseStr = restTemplateUtil.postLeQi(leqiHeader, requestJson);
        }

        Type type = new TypeToken<LeqiResult<String>>(){}.getType();
        LeqiResult<String> leqiResult = LeqiResultUtil.jsonToLeqiResult(responseStr, type);
        LeqiResult.ErrorInfo errorInfo = leqiResult.getResponse().getError();
        // 有error节点，返回error
        if (errorInfo != null) {
            return Result.ERRORT(errorInfo.getCode(), errorInfo.getMessage());
        }
        QueryRedConfirmListVO resultVo = JSONObject.parseObject(leqiResult.getResponse().getData(), QueryRedConfirmListVO.class);
        // 业务层不为00，返回error
        if (!CommonConstants.LEQI_SUCCESS.equals(resultVo.getReturncode())) {
            return Result.ERRORT(resultVo.getReturncode(), resultVo.getReturnmsg());
        }

        return Result.OK(resultVo);
    }

    /**
     * 构建乐企请求头信息
     * @param params 入参
     * @param leqiApiEnum 乐企服务编码枚举
     */
    private LeqiHeader buildHeader(BaseUserInfoParam params, LeqiApiEnum leqiApiEnum) {
        LeqiHeader leqiHeader = new LeqiHeader();
        LeqiAbilityEnum leqiAbility;
        if (TdysEnum.TDYS_05.getCode().equals(params.getTdys())) {
            leqiAbility = LeqiAbilityEnum.BDCXS;
        } else if (TdysEnum.TDYS_06.getCode().equals(params.getTdys())) {
            leqiAbility = LeqiAbilityEnum.BDCZL;
        } else if (TdysEnum.TDYS_09.getCode().equals(params.getTdys())) {
            leqiAbility = LeqiAbilityEnum.LKYS;
        } else {
            leqiAbility = LeqiAbilityEnum.BASE;
        }

        leqiHeader.setJrdwptbh(jrdwptbh);
        leqiHeader.setSydwptbh(params.getSydwptbh());
        leqiHeader.setFwbm(leqiApiEnum.getApiCode());
        leqiHeader.setNlbm(leqiAbility.getAbilityCode());
        leqiHeader.setYlbm(leqiAbility.getUseCasesCode());
        leqiHeader.setRequestUrl(url + leqiAbility.getAbilityCode() + "/" + leqiApiEnum.getApiCode() + "/");
        // 仅适用于能力开通后或能力审核中时进行沙箱调用，能力未提交审核前不要加上此参数
        if (StringUtils.isNotBlank(sxcsbz)) {
            leqiHeader.setSxcsbz(sxcsbz);
        }

        return leqiHeader;
    }
}
